import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import tanling.matplot_4j.d3d.base.pub.Range;
import tanling.matplot_4j.d3d.facade.MatPlot3DMgr;

public class Curver2dsMoveDemo {

	//数据组数量
	static int count = 5;

	//每帧步长
	static double step = 0.6;

	//两次循环停顿帧
	static final int pause = 150;

	static int pauseFrames = 0;

	static Thread thread;

	public static void main(String[] args) throws InterruptedException {
		Random ra = new Random();

		final MatPlot3DMgr matPlot3DMgr = new MatPlot3DMgr();

		final List<Point2D.Double>[] targets = new ArrayList[count];

		final List<Point2D.Double>[] start = new ArrayList[count];

		for (int c = 1; c <= targets.length; c++) {

			List<Point2D.Double> li = new ArrayList<Point2D.Double>();
			targets[c - 1] = li;

			for (int i = 0; i < 20; i++) {
				li.add(new Point2D.Double(i, i * c * 0.05 + (ra.nextDouble() * 0.8)));
			}
		}

		for (int i = 1; i <= targets.length; i++) {
			matPlot3DMgr.addData2D("Item系列 " + i, null, start[i - 1]);
		}

		matPlot3DMgr.setScaleY(0.6); // 压缩Y方向,是图形显得更薄
		matPlot3DMgr.setScaleX(1);
		matPlot3DMgr.setScaleZ(1.3);
		
		matPlot3DMgr.setBeita(4.3);
		matPlot3DMgr.setSeeta(0.3);

		matPlot3DMgr.getProcessor().setRulerYVisable(false);// 隐藏Y方向坐标轴显示
		matPlot3DMgr.getProcessor().setCoordinateSysShowType(matPlot3DMgr.getProcessor().COORDINATE_SYS_STABLE);
		matPlot3DMgr.getProcessor().setCoordinateSysTransformationType(matPlot3DMgr.getProcessor().COORDINATE_RANGE_AUTO_EXTEND);

		matPlot3DMgr.initRanges(new Range(0, 19), new Range(0, 6), new Range(0, 3));//没有数据时先预设空间范围以便fitScreem

		matPlot3DMgr.fitScreem();

		matPlot3DMgr.show();

		thread = new Thread(new Runnable() {

//			@Override
			public void run() {

				List<Point2D.Double>[] lastFrame = start.clone();

				while (true) {

					List<Point2D.Double>[] nextframe = nextFrame(start, lastFrame, targets);

					matPlot3DMgr.getProcessor().clear();

					for (int i = 1; i <= targets.length; i++) {
						matPlot3DMgr.addData2D("Item系列 " + i, null, lastFrame[i - 1]);
					}

					matPlot3DMgr.fitScreemWhenNeeded();

					try {
						matPlot3DMgr.updateView(15);
					} catch (Exception e) {
						e.printStackTrace();
					}

					lastFrame = nextframe;

					Thread.yield();
				}
			}

		});

		thread.start();

	}

	private static List<Point2D.Double>[] nextFrame(List<Point2D.Double>[] start, List<Point2D.Double>[] lastFrame,
			List<Point2D.Double>[] target) {

		int updating = -1;// 正在更新的一排

		for (int i = 0; i < lastFrame.length; i++) {

			if (lastFrame[i] == null) {

				updating = i;
				break;
			}

			Point2D.Double endPoint = lastFrame[i].get(lastFrame[i].size() - 1);
			Point2D.Double targetEndPoint = target[i].get(target[i].size() - 1);
			
			if (endPoint.getX() < targetEndPoint.getX()) {
				updating = i;
				break;
			}
		}

		if (updating == -1) {
			pauseFrames++;

			if (pauseFrames < pause) {
				return lastFrame;
			} else {
				return start.clone();
			}

		} else {

			pauseFrames = 0;

			List<Point2D.Double> lastF = lastFrame[updating];
			List<Point2D.Double> targetL = target[updating];

			if (lastF == null) {
				lastF = new ArrayList<Point2D.Double>();
				lastFrame[updating] = lastF;
			}

			if (lastF.size() == 0) {

				lastF.add(targetL.get(0));
				return lastFrame;

			} else {

				Point2D.Double eTempPoint = lastF.get(lastF.size() - 1);

				if (!targetL.contains(eTempPoint)) {
					lastF.remove(lastF.size() - 1);
				}

				double newX = eTempPoint.getX() + step;

				double frontXInFrame = eTempPoint.getX();

				int indexInT = 0;

				for (int i = 0; i < targetL.size(); i++) {

					if (targetL.get(i).getX() <= newX && targetL.get(i).getX() > frontXInFrame) {
						lastF.add(targetL.get(i));
						indexInT = i;
					}
				}

				if (indexInT == targetL.size() - 1) {
					return lastFrame;
				} else {

					Point2D.Double frontKeyP = lastF.get(lastF.size() - 1);

					int frontPIndex = targetL.indexOf(frontKeyP);

					if (targetL.size() - 1 > frontPIndex) {

						Point2D.Double behindKeyP = targetL.get(frontPIndex + 1);
						double newY = frontKeyP.y
								+ ((newX - frontKeyP.x) * (behindKeyP.y - frontKeyP.y) / (behindKeyP.x - frontKeyP.x));

						lastF.add(new Point2D.Double(newX, newY));
						return lastFrame;
					} else {

						return lastFrame;
					}
				}
			}
		}
	}
}
